package middlewares

import (
	"bytes"
	"encoding/json"
	"io/ioutil"
	"lingc/models"
	"lingc/services"
	"lingc/utils"
	"log"
	"strconv"
	"strings"

	"github.com/gin-gonic/gin"
)

// AuthMiddleware 是一个登录校验的中间件
func AuthMiddleware() gin.HandlerFunc {
	return func(c *gin.Context) {
		// 这里简单模拟一个登录校验逻辑，实际应用中可能需要从请求头或cookie中获取token并验证
		token := c.GetHeader("Authorization")

		if token == "" {
			utils.SendJSONResponse(c, utils.ErrorToken, gin.H{"msg": "未授权", "code": 1})
			c.Abort()
			return
		}

		user := utils.ValidateToken(token)
		// 验证token
		if user == nil {
			utils.SendJSONResponse(c, utils.ErrorToken, gin.H{"msg": "无效的token"})
			c.Abort()
			return
		}
		log.Printf("user:%v", user)
		// 判断用户类型
		if user.Type != "admin" {
			utils.SendJSONResponse(c, utils.ErrorToken, gin.H{"msg": "无效的token", "code": 1})
			c.Abort()
			return
		}

		//获取缓存token
		redis_token := utils.GetRedis(utils.GenerateMD5("token_" + user.Username))
		if redis_token == "" {
			utils.SendJSONResponse(c, utils.ErrorToken, gin.H{"msg": "无效的token", "code": 1})
			c.Abort()
			return
		}
		if token != redis_token {
			utils.SendJSONResponse(c, utils.ErrorToken, gin.H{"msg": "无效的token", "code": 2})
			c.Abort()
			return
		}
		// Set the user in the context
		// log.Println("user:", user)
		c.Set("user", user)
		path := strings.Replace(c.Request.URL.Path, "/api/manage/", "", 1)
		if utils.Contains(utils.WhiteList, path) {
			c.Next()
			return
		}

		rulesIdsArr := []uint{}

		rulesStr := utils.GetRedis("auth_rule_ids_" + strconv.Itoa(int(user.ID)))
		if rulesStr != "" {
			// 将JSON数据反序列化到map
			json.Unmarshal([]byte(rulesStr), &rulesIdsArr)
		} else {
			utils.SendJSONResponse(c, utils.ErrorToken, gin.H{"msg": "未授权", "code": 2})
			c.Abort()
			return
		}
		if len(rulesIdsArr) <= 0 {
			utils.SendJSONResponse(c, utils.ErrorToken, gin.H{"msg": "未授权", "code": 3})
			c.Abort()
			return
		}
		rulesMapStr := utils.GetRedis("auth_rule_map_url")
		if rulesMapStr == "" {
			utils.SendJSONResponse(c, utils.ErrorToken, gin.H{"msg": "未授权", "code": 4})
			c.Abort()
			return
		}
		mapUrl := make(map[string]*models.AuthRuleMenusName)
		err := json.Unmarshal([]byte(rulesMapStr), &mapUrl)
		if err != nil {
			utils.SendJSONResponse(c, utils.ErrorToken, gin.H{"msg": "未授权", "code": 5})
			c.Abort()
			return
		}
		key := utils.GenerateMD5(strings.ToLower(path))
		item, exists := mapUrl[key]
		if !exists {
			utils.SendJSONResponse(c, utils.ErrorToken, gin.H{"msg": "未授权", "code": 6})
			c.Abort()
			return
		}
		// log.Printf("item：%v", item.ID)
		//判断 id 在 rulesIdsArr 中
		if !utils.InArray(rulesIdsArr, item.ID) {
			utils.SendJSONResponse(c, utils.ErrorToken, gin.H{"msg": "未授权", "code": 7})
			c.Abort()
			return
		}

		// log.Printf("父级pathv：%v", pathv)
		pname := services.GetParentAllName(c, key, mapUrl)
		// 获取请求参数并打印到日志
		queryParams := c.Request.URL.Query()
		// log.Printf("GET请求参数：%v", queryParams)
		queryParamsStr, _ := json.Marshal(queryParams)
		// 读取原始请求体
		rawData, err := c.GetRawData()
		// 将请求体重新设置回原始状态
		c.Request.Body = ioutil.NopCloser(bytes.NewBuffer(rawData))
		if err == nil {
			log.Printf("pname:%v", pname)
			ishas := utils.MyhasString(path, []string{"/page", "/info"})
			log.Printf("ishas:%v", ishas)
			if !ishas {
				services.NewAuthHandleLogService(utils.MysqlClient).CreateAuthHandleLog(&models.AuthHandleLogCreate{
					AdminID: user.ID,
					Name:    pname,
					Param:   "GETData: " + string(queryParamsStr) + "POSTData: " + string(rawData),
					URL:     path,
				})
				// if errs != nil {
				// 	log.Printf("记录日志失败：%v", errs)
				// }
				// log.Printf("记录日志成功：%v", tempdata)
			}
		}

		c.Next()
	}
}
